package com.domor.xxx.framework.shiro.service;

import com.domor.xxx.common.constant.Constants;
import com.domor.xxx.common.constant.UserConstants;
import com.domor.xxx.common.exception.UserException;
import com.domor.xxx.common.utils.AddressUtils;
import com.domor.xxx.common.utils.DateUtils;
import com.domor.xxx.common.utils.spring.SpringUtils;
import com.domor.xxx.framework.shiro.util.ShiroUtils;
import com.domor.xxx.system.domain.SysLoginLog;
import com.domor.xxx.system.domain.SysUser;
import com.domor.xxx.system.service.SysLoginLogService;
import com.domor.xxx.system.service.SysUserService;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 * 登录校验方法
 * @author liyuyang
 * @date 2020/5/15
 */
@Slf4j
@Component
public class SysLoginService {

    @Autowired
    private SysPasswordService passwordService;

    @Autowired
    private SysUserService userService;

    /**
     * 登录
     */
    public SysUser login(String username, String password) {
        // 用户名或密码为空 错误
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            throw new UserException(UserException.NOT_NULL);
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            throw new UserException(UserException.PWD_ERROR);
        }

        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            throw new UserException(UserException.NOT_EXIST);
        }

        // 查询用户信息
        SysUser user = userService.selectUserByLoginName(username);

        if (user == null && maybeMobilePhoneNumber(username)) {
            user = userService.selectUserByPhone(username);
        }

        if (user == null && maybeEmail(username)) {
            user = userService.selectUserByEmail(username);
        }

        if (user == null) {
            throw new UserException(UserException.NOT_EXIST);
        }

        if (user.getDeleteFlag() == 1) {
            throw new UserException(UserException.USER_DELETE);
        }

        if (user.getStatus() == 1) {
            throw new UserException(UserException.USER_BLOCKED);
        }

        passwordService.validate(user, password);

        updateUserLoginInfo(user);
        return user;
    }

    private boolean maybeEmail(String username) {
        if (!username.matches(UserConstants.EMAIL_PATTERN)) {
            return false;
        }
        return true;
    }

    private boolean maybeMobilePhoneNumber(String username) {
        if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN)) {
            return false;
        }
        return true;
    }

    /**
     * 记录登陆信息
     *
     * @param username 用户名
     * @param status   状态
     * @param message  消息
     * @return 任务task
     */
    @Async("asyncServiceExecutor")
    public void recordLoginInfo(String username, String status, String message, UserAgent userAgent) {
        String ip = ShiroUtils.getIp();
        String address = AddressUtils.getRealAddressByIP(ip);
        StringBuilder s = new StringBuilder();
        s.append(getBlock(ip));
        s.append(address);
        s.append(getBlock(username));
        s.append(getBlock(status));
        s.append(getBlock(message));
        // 打印信息到日志
        log.info(s.toString());
        // 获取客户端操作系统
        String os = userAgent.getOperatingSystem().getName();
        // 获取客户端浏览器
        String browser = userAgent.getBrowser().getName();
        // 封装对象
        SysLoginLog logininfor = new SysLoginLog();
        logininfor.setLoginName(username);
        logininfor.setIpaddr(ip);
        logininfor.setLoginLocation(address);
        logininfor.setBrowser(browser);
        logininfor.setOs(os);
        logininfor.setMsg(message);
        // 日志状态
        if (com.domor.xxx.common.utils.StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
            logininfor.setStatus(Constants.SUCCESS);
        } else if (Constants.LOGIN_FAIL.equals(status)) {
            logininfor.setStatus(Constants.FAIL);
        }
        // 插入数据
        SpringUtils.getBean(SysLoginLogService.class).insertLoginLog(logininfor);
    }

    /**
     * 记录登录信息
     * 用户表记录登录时间和IP
     */
    public void updateUserLoginInfo(SysUser user) {
        user.setLoginIp(ShiroUtils.getIp());
        user.setLoginDate(DateUtils.getNowDate());
        userService.updateUserInfo(user);
    }

    private static String getBlock(Object msg) {
        if (msg == null) {
            msg = "";
        }
        return "[" + msg.toString() + "]";
    }

}
